﻿using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace Lucene.Net.Store.Azure
{
    public class AzureDirectory : BaseDirectory
    {
        private CloudBlobClient _blobClient;
        /// <summary>
        /// Create an AzureDirectory
        /// </summary>
        /// <param name="storageAccount">storage account to use</param>
        /// <param name="containerName">name of container (folder in blob storage)</param>
        /// <param name="cacheDirectory"></param>
        public AzureDirectory(
            CloudStorageAccount storageAccount,
            string containerName, Directory cacheDirectory)
        {
            if (storageAccount == null)
                throw new ArgumentNullException("storageAccount");
            CacheDirectory = cacheDirectory;
            _blobClient = storageAccount.CreateCloudBlobClient();
            BlobContainer = _blobClient.GetContainerReference(containerName);
            BlobContainer.CreateIfNotExistsAsync().Wait();
        }

        public CloudBlobContainer BlobContainer { get; }
        public Directory CacheDirectory { get; }

        /// <summary>Returns an array of strings, one for each file in the directory. </summary>
        public override String[] ListAll()
        {
            var results = from blob in ListBlobsAsync(BlobContainer).Result
                          select blob.Uri.AbsolutePath.Substring(blob.Uri.AbsolutePath.LastIndexOf('/') + 1);
            return results.ToArray<string>();
        }

        private async Task<List<IListBlobItem>> ListBlobsAsync(CloudBlobContainer container)
        {
            BlobContinuationToken continuationToken = null;
            List<IListBlobItem> results = new List<IListBlobItem>();
            do
            {
                bool useFlatBlobListing = true;
                BlobListingDetails blobListingDetails = BlobListingDetails.None;
                int maxBlobsPerRequest = 500;
                var response = await container.ListBlobsSegmentedAsync("", useFlatBlobListing, blobListingDetails, maxBlobsPerRequest, continuationToken, null, null);
                continuationToken = response.ContinuationToken;
                results.AddRange(response.Results);
            }
            while (continuationToken != null);
            return results;
        }

        /// <summary>Returns true if a file with the given name exists. </summary>
        public override bool FileExists(String name)
        {
            return BlobContainer.GetBlobReference(name) != null;
        }

        /// <summary>Removes an existing file in the directory. </summary>
        public override void DeleteFile(System.String name)
        {
            var blob = BlobContainer.GetBlockBlobReference(name);
            blob?.DeleteIfExistsAsync().Wait();
        }


        /// <summary>Returns the length of a file in the directory. </summary>
        public override long FileLength(String name)
        {
            var blob = BlobContainer.GetBlockBlobReference(name);
            blob.FetchAttributesAsync().Wait();
            return blob.Properties.Length; // fall back to actual blob size
        }

        public override IndexOutput CreateOutput(string name, IOContext context)
        {
            throw new NotImplementedException();
        }

        public override void Sync(ICollection<string> names)
        {
            throw new NotImplementedException();
        }

        public override IndexInput OpenInput(string name, IOContext context)
        {
            var blob = BlobContainer.GetBlobReference(name);
            return new AzureIndexInput(blob, blob.Uri.ToString());
        }


        /// <summary>Closes the store. </summary>
        protected override void Dispose(bool disposing)
        {
            _blobClient = null;
        }



    }

}
